﻿using System;
using System.Collections.Generic;
using AudioStudio;
using UnityEngine;
using UnityEngine.UI;
using Yoozoo.Framework.Core;
using Yoozoo.Gta.Common;
using Yoozoo.Libs;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Yoozoo.Mars.Got;
using Yoozoo.UI.YGUI;

namespace Gameplay.PVE.Survivor
{
    
    public class MeshApplyData : IClass
    {
        public MeshRenderer renderer;
        public bool materialReady = false;
        public Material material;

        public void ApplyMaterial(Material mat)
        {
            renderer.material = mat;
            materialReady = true;
            material = renderer.material;
        }
        public void OnReset()
        {
            materialReady = false;
            renderer = null;
        }
    }
    public class BattleResourceManager: BattleSingleton<BattleResourceManager>
    {
        private ResLoader resLoader;
        
        public HashSet<int> soundBank = new HashSet<int>();
        private static Dictionary<int, string> bankNameMap = new Dictionary<int, string>
        {
            { 41000, "Frank" },
            { 41001, "Beverly" },
            { 41002, "Charles" },
            { 41003, "Amy" },
            { 41004, "Arthur" },
            { 41005, "Okada" },
            { 41006, "Samantha" },
            { 41007, "Joan" },
            { 41008, "Claire" },
            { 41009, "Danny" },
            { 41010, "Audrey" },
            { 41011, "Belt" },
            { 41012, "Phoenix" },
            { 41013, "Jim" },
            { 41014, "Gavin" },
            { 41017, "Rene" },
            { 41018, "Talita" },
            { 41019, "Kelly" },
            { 41020, "Oleg" },
            { 41022, "Maeda" },
            { 41023, "Karl" },
            { 41024, "Tuco" },
            { 99999, "Enemy" }
        };

        private List<string> defaultBankList = new List<string>
        {
            "Ambience",
            "Ambience_FirstPackage",
        };

        private Material uiOverlayMaterial;
        private List<MaskableGraphic> readyToApplyMaterialList = new List<MaskableGraphic>();
        
        public override void Initialize()
        {
            resLoader = ResLoader.Alloc();
            for (int i = 0; i < defaultBankList.Count; i++)
            {
                AudioManager.LoadBank(defaultBankList[i]);
            }
            InitLoading();
            resLoader.Add2Load("Assets/ResourcesAssets/Materials/mat_UI_Overlay.mat", (path,success,res) =>
            {
                uiOverlayMaterial = res as Material;
                for (int i = 0; i < readyToApplyMaterialList.Count; i++)
                {
                    readyToApplyMaterialList[i].material = uiOverlayMaterial;
                }
                readyToApplyMaterialList.Clear();
                return;
            });
            resLoader.Add2Load("Assets/ResourcesAssets/Pve/Materials/mat_hero_phantom.mat", (path,success,res) =>
            {
                phantomMaterial = res as Material;
                phantomMaterial.renderQueue = 4000;
                for (int i = 0; i < readyToApplyPhantomMaterialList.Count; i++)
                {
                    readyToApplyPhantomMaterialList[i].ApplyMaterial(phantomMaterial);
                }
                readyToApplyPhantomMaterialList.Clear();
                return;
            });
        }

        private Material phantomMaterial;
        private List<MeshApplyData> readyToApplyPhantomMaterialList = new List<MeshApplyData>();

        
        public bool ApplyPhantomMaterial(MeshApplyData renderer)
        {
            if (phantomMaterial == null)
            {
                readyToApplyPhantomMaterialList.Add(renderer);
                return false;
            }
            renderer.ApplyMaterial(phantomMaterial);
            return true;
        }
        
        public void ApplyUIOverlayMaterial(Transform transform)
        {
            var graphics = transform.GetComponentsInChildren<MaskableGraphic>();
            if (uiOverlayMaterial == null)
            {
                for (int i = 0; i < graphics.Length; i++)
                {
                    readyToApplyMaterialList.Add(graphics[i]);
                }
                return;
            }
            for (int i = 0; i < graphics.Length; i++)
            {
                graphics[i].material = uiOverlayMaterial;
            }
        }

        public void LoadPrefabByPath(string path, Res.ResLoadCompleteCallBack callback)
        {
            resLoader.Add2Load(path,callback);
            resLoader.Load();
        }

        public void RecoverPrefabByPath(string path, GameObject prefab)
        {
            GameObject.Destroy(prefab);
        }

        public static string GetResourcePath(int resId)
        {
            var realId = resId;
            return BattleConfigManager.Instance.GetResourceConfig(realId).path + ".prefab";
        }
        
        public static string GetEffectPathByName(string name)
        {
            return string.Format("Assets/ResourcesAssets/Prefabs/Effect/Battle/Rpg/{0}.prefab",name);
        }

        public void LoadSoundBank(int id)
        {
            if (soundBank.Contains(id))
            {
                return;
            }

            if (bankNameMap.TryGetValue(id, out var name))
            {
                AudioManager.LoadBank(name);
            }
        }

        private Dictionary<ELoadingResourceType, int> resourceWeight = new Dictionary<ELoadingResourceType, int>
        {
            { ELoadingResourceType.MapData, 2 },
            { ELoadingResourceType.MapNavMesh, 2 },
            { ELoadingResourceType.MapResource, 2 },
            //{ ELoadingResourceType.MainUnit, 1 },
            //{ ELoadingResourceType.Timeline, 1 },
            { ELoadingResourceType.Camera, 1 },
            //{ ELoadingResourceType.StagePoint, 1 },
        };

        private HashSet<ELoadingResourceType> loadedType = new HashSet<ELoadingResourceType>();

        private int totalWeight = 0;
        private int currentWeight = 0;
        
        public void InitLoading()
        {
            loadedType.Clear();
            totalWeight = 0;
            currentWeight = 0;
            foreach (var weight in resourceWeight.Values)
            {
                totalWeight += weight;
            }
        }

        private Action loadCompleteCallback;
        
        public void SetLoadCompleteCallback(Action action)
        {
            loadCompleteCallback = action;
        }
        
        public void LoadComplete(ELoadingResourceType type)
        {
            if (loadedType.Contains(type))
            {
                return;
            }
            loadedType.Add(type);
            currentWeight += resourceWeight[type];
            if (BattleDebug.enableLog)
            {
                BattleDebug.Log("LoadComplete " + type + " " + currentWeight + " " + totalWeight);
            }
            if (currentWeight >= totalWeight)
            {
                loadCompleteCallback?.Invoke();
                loadCompleteCallback = null;
                Timers.inst.CallLater((o) =>
                {
                    ResidentHandler.Inst.GetFunction("L_SurvivorManager.UpdateLoadingProgress").Action(currentWeight * 100f / (float)totalWeight);
                });
            }
            else
            {
                ResidentHandler.Inst.GetFunction("L_SurvivorManager.UpdateLoadingProgress").Action(currentWeight * 100f / (float)totalWeight);
            }
        }
        
        public override void Dispose()
        {
            if (resLoader != null)
            {
                resLoader.Recycle2Cache();
                resLoader = null;
            }
            totalWeight = 0;
            currentWeight = 0;
        }
    }
}
